package util.generic;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * @author Jorge Diaz
 * Redocumentado Ramon De La Cruz
 */
public class GenericUtil {

    /**
     * Devuelve el primer parametro de la clase generica
     * 
     * @param clazz
     *            La clase generica donde se buscaran los parametros
     * @return El primer parametro, o <code>null</code> si no puede ser
     *         determinado
     */
    @SuppressWarnings("rawtypes")
    public static Class getParametroGenericSuperClass(Class clazz) {
        return getParametroGenericSuperClass(clazz, 0);
    }

    /**
     * Devuelve el parámetro, segun el indice indicado, de la clase generica 
     * 
     * @param clazz
     *            La clase generica donde se buscaran los parametros. Class<P0,P1,P2,...>
     * @param index
     *            El indice del parametro que estamos buscando
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static Class getParametroGenericSuperClass(Class clazz, int index) {
        Type genType = clazz.getGenericSuperclass();

        //Type[] params = null;
        if (genType instanceof ParameterizedType) {
            Type[] params = ((ParameterizedType) genType)
                            .getActualTypeArguments();            
            
            if ((params != null) && (params.length >= (index - 1))) {
                return (Class) params[index];
            }
        }        
        return null;
        //return getParametro(params,index);
    }

    /**
     * Creado Por Ramon De la Cruz
     * 
     * @param clazz
     * @param index
     * @return 
     */
    /*
    @SuppressWarnings("rawtypes")
    public static Class getParametroGenericClass(Class clazz, int index) {        
        return getParametro(clazz.getTypeParameters(), index);
    }*/

    
    @SuppressWarnings("rawtypes")
    private static Class getParametro(Type[] params, int index) {
        System.out.println(params[0].getClass());
        System.out.println(params.length);
        if ((params != null) && (params.length >= (index - 1))) {
            return (Class) params[index];
        }
        return null;
    }
	
    /**
     * Creado Por Ramon De la Cruz
     * No funciona bien para:
     * public class ListaEnlazada<E extends Elemento, N extends Nodo<E>>
     * @param clazz
     * @param index
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException 
     */
    /*
    @SuppressWarnings("rawtypes")
    public static Object newInstanciaParametroGenericClass(Class clazz, int index) 
            throws InstantiationException, IllegalAccessException {
        return getParametroGenericClass(clazz, index).newInstance();            
    }

    public static Object newInstanciaParametroGenericClass(Class clazz) 
            throws InstantiationException, IllegalAccessException {
        return newInstanciaParametroGenericClass(clazz, 0);
    }*/

    /**
     * Creado Por Ramon De la Cruz
     * @param clazz La clase generica donde se buscaran los parametros
     * @return Devuelve una instancia del primer parametro de la clase generica
     * @throws InstantiationException
     * @throws IllegalAccessException 
     */
    @SuppressWarnings("rawtypes")
    public static Object newInstanciaParametroGenericSuperClass(Class clazz) 
            throws InstantiationException, IllegalAccessException {
        return getParametroGenericSuperClass(clazz, 0).newInstance();           
    }
    
   
}